﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Aribaccio.Security
{
    [ComVisible(true)]
    [ComSourceInterfaces(typeof(ISecurity))]
    [ClassInterface(ClassInterfaceType.AutoDispatch)]
    public class SecurityDES3 : ISecurity
    {
        /// <summary>
        /// 默认安全密钥，密钥必须为8位[安全密钥1]
        /// </summary>
        protected string DefaultSecretKey = "SECRETK1";
        /// <summary>
        /// 默认安全密钥，密钥必须为8位[同星公司公钥2]
        /// </summary>
        protected string DefaultSecretKey2 = "SECRETK2";
        /// <summary>
        /// 默认安全密钥，密钥必须为8位[同星公司公钥3]
        /// </summary>
        protected string DefaultSecretKey3 = "SECRETK3";
        /// <summary>
        /// 用于对称算法的初始化向量
        /// </summary>
        protected byte[] DefaultRgbIV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
        /// <summary>
        /// 安全密钥,密钥必须为8位
        /// </summary>
        public string SecretKey { get; set; }
        /// <summary>
        /// 安全密钥,密钥必须为8位
        /// </summary>
        public string SecretKey2 { get; set; }
        /// <summary>
        /// 安全密钥,密钥必须为8位
        /// </summary>
        public string SecretKey3 { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public SecurityDES3()
        {
            this.SecretKey = string.Empty;
            this.SecretKey2 = string.Empty;
            this.SecretKey3 = string.Empty;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="argSecretKey">安全密钥,密钥必须为8位</param>
        /// <param name="argSecretKey2">安全密钥2,密钥必须为8位</param>
        /// <param name="argSecretKey3">安全密钥3,密钥必须为8位</param>
        public SecurityDES3(string argSecretKey, string argSecretKey2, string argSecretKey3)
        {
            this.SecretKey = argSecretKey;
            this.SecretKey2 = argSecretKey2;
            this.SecretKey3 = argSecretKey3;
        }

        /// <summary>
        /// 3DES 加密(基于DES，对一块数据用三个不同的密钥进行三次加密，强度更高)
        /// </summary>
        /// <param name="argEncryptString">待加密密文</param>
        /// <returns>加密字符串</returns>
        public string Encrypt(string argEncryptString)
        {
            string resultEncrypt = "";
            try
            {
                if (string.IsNullOrWhiteSpace(this.SecretKey)) { this.SecretKey = DefaultSecretKey; }
                if (string.IsNullOrWhiteSpace(this.SecretKey2)) { this.SecretKey2 = DefaultSecretKey2; }
                if (string.IsNullOrWhiteSpace(this.SecretKey3)) { this.SecretKey3 = DefaultSecretKey3; }
                resultEncrypt = this.Encrypt(argEncryptString, this.SecretKey3);
                resultEncrypt = this.Encrypt(resultEncrypt, this.SecretKey2);
                resultEncrypt = this.Encrypt(resultEncrypt, this.SecretKey);
            }
            catch (Exception) { resultEncrypt = string.Empty; }
            return resultEncrypt;
        }

        /// <summary>
        /// 3DES 解密(基于DES，对一块数据用三个不同的密钥进行三次加密，强度更高)
        /// </summary>
        /// <param name="argDecryptString">待解密密文</param>
        /// <returns>returns</returns>
        public string Decrypt(string argDecryptString)
        {
            string resultDecrypt = "";
            try
            {
                if (string.IsNullOrWhiteSpace(this.SecretKey)) { this.SecretKey = DefaultSecretKey; }
                if (string.IsNullOrWhiteSpace(this.SecretKey2)) { this.SecretKey2 = DefaultSecretKey2; }
                if (string.IsNullOrWhiteSpace(this.SecretKey3)) { this.SecretKey3 = DefaultSecretKey3; }
                resultDecrypt = this.Decrypt(argDecryptString, this.SecretKey);
                resultDecrypt = this.Decrypt(resultDecrypt, this.SecretKey2);
                resultDecrypt = this.Decrypt(resultDecrypt, this.SecretKey3);
            }
            catch (Exception) { resultDecrypt = string.Empty; }
            return resultDecrypt;
        }


        /// <summary>
        /// DES 加密(数据加密标准，速度较快，适用于加密大量数据的场合)
        /// </summary>
        /// <param name="argEncryptString">待加密的密文</param>
        /// <param name="argEncryptKey">加密的密钥</param>
        /// <returns>returns</returns>
        protected string Encrypt(string argEncryptString, string argEncryptKey)
        {
            //检查，密文不得为空
            if (string.IsNullOrWhiteSpace(argEncryptString)) { return string.Empty; }
            //检查，密钥必须为8位
            if (string.IsNullOrWhiteSpace(argEncryptKey) || argEncryptKey.Length != 8) { return string.Empty; }
           
            string resultEncrypt = "";
            DES desProvider = DES.Create();
            try
            {
                byte[] encryptBytes = Encoding.Default.GetBytes(argEncryptString);
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, desProvider.CreateEncryptor(Encoding.Default.GetBytes(this.SecretKey), DefaultRgbIV), CryptoStreamMode.Write);
                cStream.Write(encryptBytes, 0, encryptBytes.Length);
                cStream.FlushFinalBlock();
                resultEncrypt = Convert.ToBase64String(mStream.ToArray());
                mStream.Close(); mStream.Dispose();
                cStream.Close(); cStream.Dispose();
            }
            catch (IOException) { resultEncrypt = string.Empty; }
            catch (CryptographicException) { resultEncrypt = string.Empty; }
            catch (ArgumentException) { resultEncrypt = string.Empty; }
            catch (Exception) { resultEncrypt = string.Empty; }
            finally { desProvider.Clear(); }
            return resultEncrypt;
        }

        /// <summary>
        /// DES 解密(数据加密标准，速度较快，适用于加密大量数据的场合)
        /// </summary>
        /// <param name="argDecryptString">待解密的密文</param>
        /// <param name="argDecryptKey">解密的密钥</param>
        /// <returns>returns</returns>
        protected string Decrypt(string argDecryptString, string argDecryptKey)
        {
            //检查，密文不得为空
            if (string.IsNullOrWhiteSpace(argDecryptString)) { return string.Empty; }
            //检查，密钥必须为8位
            if (string.IsNullOrWhiteSpace(argDecryptKey) || argDecryptKey.Length != 8) { return string.Empty; }
            
            string resultDecrypt = "";
            DES desProvider = DES.Create();
            try
            {
                byte[] decryptBytes = Convert.FromBase64String(argDecryptString);
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, desProvider.CreateDecryptor(Encoding.Default.GetBytes(argDecryptKey), DefaultRgbIV), CryptoStreamMode.Write);
                cStream.Write(decryptBytes, 0, decryptBytes.Length);
                cStream.FlushFinalBlock();
                resultDecrypt = Encoding.Default.GetString(mStream.ToArray());
                mStream.Close(); mStream.Dispose();
                cStream.Close(); cStream.Dispose();
            }
            catch (IOException) { resultDecrypt = string.Empty; }
            catch (CryptographicException) { resultDecrypt = string.Empty; }
            catch (ArgumentException) { resultDecrypt = string.Empty; }
            catch (Exception) { resultDecrypt = string.Empty; }
            finally { desProvider.Clear(); }
            return resultDecrypt;
        }
    }
}
